home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / msn / MSNSocket.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  12KB  |  396 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import with_statement
  5. import socket
  6. import threading
  7. import logging
  8. log = logging.getLogger('msn.sock')
  9. from collections import defaultdict
  10. from threading import RLock
  11. import common
  12. from util import callsback, lock, default_timer, to_hex, get
  13. from util.Events import EventMixin, event
  14. from Msnifier import Msnifier
  15. from MSNCommands import CommandProcessor, Message
  16. import msn
  17.  
  18. dummy = lambda *a, **k: pass
  19.  
  20. def trid(max = 2147483647, i = 0):
  21.     while True:
  22.         i += 1
  23.         yield i
  24.         if i == max:
  25.             i = 0
  26.             continue
  27.  
  28.  
  29. class MSNSocketBase(EventMixin):
  30.     events = EventMixin.events | set(('on_connect', 'on_send', 'on_conn_error', 'on_close', 'on_message'))
  31.     delim = '\r\n'
  32.     payload_commands = 'MSG UUX UBX PAG IPG NOT GCF ADL UUN UBN RML FQY 241 508 UBM UUM'.split()
  33.     
  34.     def __init__(self):
  35.         EventMixin.__init__(self)
  36.         self.trid = trid()
  37.         self.callbacks = defaultdict(list)
  38.         if not hasattr(self, '_lock'):
  39.             self._lock = threading.RLock()
  40.         
  41.  
  42.     
  43.     def set_trid(self, msgobj, trid):
  44.         if trid is True:
  45.             msgobj.trid = self.trid.next()
  46.         
  47.  
  48.     
  49.     def set_callbacks(self, msgobj, callback):
  50.         if callback is sentinel:
  51.             callback = None
  52.         
  53.         if msgobj.is_trid:
  54.             self.callbacks[msgobj.trid].append(callback)
  55.         else:
  56.             self.callbacks[msgobj.cmd].append(callback)
  57.  
  58.     
  59.     def pause(self):
  60.         pass
  61.  
  62.     
  63.     def unpause(self):
  64.         pass
  65.  
  66.     
  67.     def on_connect(self):
  68.         return self
  69.  
  70.     on_connect = event(on_connect)
  71.     
  72.     def on_send(self, data):
  73.         pass
  74.  
  75.     on_send = event(on_send)
  76.     
  77.     def on_conn_error(self, e = None):
  78.         log.info('%r had a connection error: %r', self, e)
  79.         return (self, e)
  80.  
  81.     on_conn_error = event(on_conn_error)
  82.     
  83.     def on_close(self):
  84.         return self
  85.  
  86.     on_close = event(on_close)
  87.     
  88.     def on_message(self, msg):
  89.         self.event('on_message', msg)
  90.         self._lock.__enter__()
  91.         
  92.         try:
  93.             callback = None
  94.             if msg.cmd == 'QNG':
  95.                 msg.cmd = 'PNG'
  96.                 msg.trid = 0
  97.             
  98.             
  99.             try:
  100.                 if not msg.trid:
  101.                     pass
  102.                 callback = self.callbacks[msg.cmd][0]
  103.             except (KeyError, IndexError):
  104.                 e = None
  105.                 pop = False
  106.  
  107.             pop = True
  108.             if callback is None:
  109.                 return None
  110.             
  111.             if pop:
  112.                 if msg.is_trid:
  113.                     for i in range(msg.trid):
  114.                         
  115.                         try:
  116.                             self.callbacks.pop(i)
  117.                         continue
  118.                         except (IndexError, KeyError):
  119.                             continue
  120.                         
  121.  
  122.                     
  123.                 elif not msg.trid:
  124.                     self.callbacks[msg.cmd].pop(0)
  125.                 
  126.         finally:
  127.             pass
  128.  
  129.         
  130.         try:
  131.             if msg.is_error:
  132.                 f = callback.error
  133.             else:
  134.                 f = callback.success
  135.         except AttributeError:
  136.             self._lock
  137.             e = self._lock
  138.             log.error('AttributeError in msnsocket.on_message: %r\ncallback was: %r', e, callback)
  139.         except:
  140.             self._lock
  141.  
  142.         log.debug('MSNSocket calling %r', f)
  143.         
  144.         try:
  145.             f(self, msg)
  146.         except Exception:
  147.             self._lock
  148.             e = self._lock
  149.             log.error('Error in callback')
  150.             import traceback as traceback
  151.             traceback.print_exc()
  152.             import inspect as inspect
  153.             print inspect.getsource(f)
  154.         except:
  155.             self._lock
  156.  
  157.  
  158.  
  159.  
  160. class MSNSocket(MSNSocketBase, common.socket):
  161.     speed_limit = 2000
  162.     speed_window = 0.25
  163.     
  164.     def __init__(self):
  165.         common.socket.__init__(self)
  166.         MSNSocketBase.__init__(self)
  167.         self.set_terminator(self.delim)
  168.         self.data = ''
  169.         self.expecting = 'command'
  170.         self._server = None
  171.         self.rater = Msnifier(self)
  172.         self.rater.start()
  173.         self._bc_lock = RLock()
  174.         self.bytecount = [
  175.             (0, default_timer())]
  176.         log.debug('%r created', self)
  177.  
  178.     
  179.     def get_local_sockname(self):
  180.         return self.socket.getsockname()
  181.  
  182.     
  183.     def connect_args_for(self, type, addr):
  184.         return (addr,)
  185.  
  186.     
  187.     def connect(self, host_port):
  188.         
  189.         try:
  190.             (host, port) = host_port
  191.         except (ValueError, TypeError):
  192.             raise TypeError("%r address must be <type 'tuple'> (host, port) not %r (%r)", type(self).__name__, type(host_port), host_port)
  193.  
  194.         if self._server is not None:
  195.             raise ValueError("Don't know which server to use! self._server = %r, host_port = %r.", self._server, host_port)
  196.         
  197.         self._server = host_port
  198.         log.info('connecting socket to %r', self._server)
  199.         
  200.         try:
  201.             common.socket.connect(self, self._server, error = self.on_conn_error)
  202.         except Exception:
  203.             e = None
  204.             self.on_conn_error(e)
  205.             return None
  206.  
  207.         self.bind_event('on_message', (lambda msg: log.debug('Received %r', msg)))
  208.  
  209.     _connect = connect
  210.     
  211.     def _disconnect(self):
  212.         self.close_when_done()
  213.  
  214.     
  215.     def _closed(self):
  216.         return not getattr(self.socket, 'connected', False)
  217.  
  218.     _closed = property(_closed)
  219.     
  220.     def __repr__(self):
  221.         
  222.         try:
  223.             s = 'connected to %r' % (self.socket.getpeername(),)
  224.         except socket.error:
  225.             s = 'not connected'
  226.  
  227.         return '<%s %s>' % (type(self).__name__, s)
  228.  
  229.     
  230.     def test_connection(self, callback = None):
  231.         self.send(Message('PNG'), callback = callback)
  232.  
  233.     test_connection = callsback(test_connection)
  234.     
  235.     def handle_connect(self):
  236.         log.debug('connection established')
  237.         self.on_connect()
  238.  
  239.     
  240.     def handle_expt(self):
  241.         log.warning('OOB data. self.data = %r', self.data)
  242.         self.close()
  243.  
  244.     
  245.     def collect_incoming_data(self, data):
  246.         self.data += data
  247.  
  248.     collect_incoming_data = lock(collect_incoming_data)
  249.     
  250.     def set_terminator(self, term):
  251.         common.socket.set_terminator(self, term)
  252.  
  253.     
  254.     def found_terminator(self):
  255.         self.data += self.delim
  256.         
  257.         try:
  258.             self._lock.__enter__()
  259.             
  260.             try:
  261.                 self.data = ''
  262.                 data = self.data
  263.                 log.debug_s('IN  : %r', data)
  264.                 dlist = data.split(' ')
  265.                 cmd = dlist[0]
  266.                 if self.expecting == 'command' and dlist[0] in self.payload_commands:
  267.                     self.expecting = 'payload'
  268.                     self.data = data
  269.                     
  270.                     try:
  271.                         new_term = int(dlist[-1])
  272.                     except ValueError:
  273.                         self._lock
  274.                         self._lock
  275.                         self
  276.                         new_term = 0
  277.                     except:
  278.                         self._lock
  279.  
  280.                     return self.set_terminator(new_term)
  281.                 elif self.expecting == 'payload':
  282.                     self.expecting = 'command'
  283.                     data = data[:-len(self.delim)]
  284.                     payload = True
  285.                 else:
  286.                     payload = False
  287.                 self.set_terminator(self.delim)
  288.                 msg = Message.from_net(data, payload)
  289.             finally:
  290.                 pass
  291.  
  292.         except Exception:
  293.             self
  294.             e = self
  295.             log.info('error parsing message, testing connection\nError was %r', e)
  296.             self.test_connection(success = self.conn_ok, error = self.conn_error)
  297.             import traceback
  298.             traceback.print_exc()
  299.         except:
  300.             self
  301.  
  302.         self.on_message(msg)
  303.  
  304.     
  305.     def handle_close(self):
  306.         log.warning('socket closed, self.data = %r', self.data)
  307.         self.rater.stop()
  308.         self.close()
  309.  
  310.     
  311.     def close(self):
  312.         log.warning('socket closing, self.data = %r', self.data)
  313.         common.socket.close(self)
  314.         self.on_close()
  315.  
  316.     
  317.     def send_gen(self, gen, priority = 5):
  318.         self.rater.send_pkt(gen, priority)
  319.  
  320.     
  321.     def send(self, msgobj, trid = sentinel, callback = None, **kw):
  322.         self.set_trid(msgobj, trid)
  323.         log.debug('Sending %r', msgobj)
  324.         self.rater.send_pkt(str(msgobj), **kw)
  325.         self.set_callbacks(msgobj, callback)
  326.  
  327.     send = callsback(send)
  328.     
  329.     def conn_ok(self):
  330.         log.info('connection test passed')
  331.  
  332.     
  333.     def conn_error(self):
  334.         log.warning('connection test failed')
  335.         self.close_when_done()
  336.         self.on_conn_error()
  337.  
  338.     
  339.     def _send(self, data, *a, **k):
  340.         log.log_s(0, 'sent: %s' % data)
  341.         self._lock.__enter__()
  342.         
  343.         try:
  344.             log.debug_s('OUT : %r %r %r' % (data, a, k))
  345.             if not common.socket.send(self, data, *a, **k):
  346.                 log.critical('Message dropped in MSNSocket: <%s>' % data)
  347.         finally:
  348.             pass
  349.  
  350.         self.on_send(data)
  351.         now = default_timer()
  352.         self._bc_lock.__enter__()
  353.         
  354.         try:
  355.             self.bytecount.append((len(data), now))
  356.         finally:
  357.             pass
  358.  
  359.  
  360.     
  361.     def time_to_send(self, data):
  362.         now = default_timer()
  363.         self._bc_lock.__enter__()
  364.         
  365.         try:
  366.             self.bytecount = (self._bc_lock, filter)((lambda t: now - t[1] < self.speed_window), self.bytecount)
  367.         finally:
  368.             pass
  369.  
  370.         send_rate = sum((lambda .0: for b in .0:
  371. b[0])(self.bytecount))
  372.         if send_rate < self.speed_limit:
  373.             return 0
  374.         
  375.         log.debug('sending too fast')
  376.         bytes = dlen = len(data)
  377.         for size, tstamp in reversed(self.bytecount):
  378.             bytes += size
  379.             interval = now - tstamp
  380.             if (bytes / interval) * self.speed_window > self.speed_limit:
  381.                 break
  382.                 continue
  383.         
  384.         tts = (bytes / self.speed_limit) * self.speed_window + interval
  385.         log.log(5, 'currently sending at %d bytes/sec', send_rate)
  386.         log.debug('sleeping for %r seconds' % tts)
  387.         return tts
  388.  
  389.     
  390.     def close_when_done(self):
  391.         self.send(Message('OUT'))
  392.         self.rater.stop()
  393.         common.socket.close_when_done(self)
  394.  
  395.  
  396.